<?php
/**
 * DBShop 电子商务系统
 *
 * ==========================================================================
 * @link      https://www.dbshop.net/
 * @copyright 北京珑大钜商科技有限公司，并保留所有权利。
 * @license   https://www.dbshop.net/license.html License
 * ==========================================================================
 *
 * @author    静静的风 <baron@loongdom.cn>
 *
 */

namespace Shop\Controller;

use Admin\Data\Common;
use Doctrine\ORM\EntityManager;
use Laminas\Mvc\I18n\Translator;
use Laminas\View\Model\JsonModel;
use Laminas\View\Model\ViewModel;
use Operation\Entity\RechargeCode;
use Operation\Service\RechargeCodeManager;
use Shop\Common\ShopCommon;
use Shop\Form\AddUserWithdrawForm;
use Shop\Form\UserRechargeCodeForm;
use Shop\Form\UserRechargeForm;
use User\Entity\BalanceLog;
use User\Entity\User;
use User\Entity\UserRecharge;
use User\Entity\UserWithdraw;
use User\Service\BalanceLogManager;
use User\Service\UserManager;
use User\Service\UserRechargeManager;
use User\Service\UserWithdrawManager;

class HomeUserBalanceController extends HomeActionController
{
    private $translator;
    private $entityManager;
    private $writeEntityManager;
    private $userRechargeManager;
    private $userWithdrawManager;
    private $userManager;
    private $balanceLogManager;
    private $rechargeCodeManager;

    public function __construct(
        Translator      $translator,
        EntityManager   $entityManager,
        EntityManager   $writeEntityManager,
        UserRechargeManager $userRechargeManager,
        UserWithdrawManager $userWithdrawManager,
        UserManager         $userManager,
        BalanceLogManager   $balanceLogManager,
        RechargeCodeManager $rechargeCodeManager
    )
    {
        $this->translator   = $translator;
        $this->entityManager= $entityManager;
        $this->writeEntityManager   = $writeEntityManager;
        $this->userRechargeManager  = $userRechargeManager;
        $this->userWithdrawManager  = $userWithdrawManager;
        $this->userManager  = $userManager;
        $this->balanceLogManager    = $balanceLogManager;
        $this->rechargeCodeManager  = $rechargeCodeManager;
    }

    /**
     * 我的余额
     * @return array|\Laminas\View\Model\ViewModel
     */
    public function indexAction()
    {
        $this->layout()->setVariable('titleName', $this->translator->translate('我的余额'));

        $userInfo = $this->entityManager->getRepository(User::class)->findOneBy(['userId' => parent::$userId]);

        $search     = [];
        $page       = (int) $this->params()->fromQuery('page', 1);
        $query      = $this->entityManager->getRepository(BalanceLog::class)->shopFindUserBalanceLog(parent::$userId, $search);
        $paginator  = $this->shopPlugin()->shopPaginator($query, $page);

        $sameCurrency = ($this->shopPlugin()->getShopDefaultCurrency()['code'] == Common::configValue('default', 'currency')['code']);

        return ['userInfo' => $userInfo, 'userBalanceLog' => $paginator, 'sameCurrency' => $sameCurrency];
    }

    /**
     * 充值码充值
     * @return \Laminas\Http\Response|UserRechargeCodeForm[]
     */
    public function rechargeCodeAction()
    {
        $this->layout()->setVariable('titleName', $this->translator->translate('充值码充值'));

        $form = new UserRechargeCodeForm($this->entityManager);
        if($this->getRequest()->isPost()) {
            $data = $this->params()->fromPost();
            $form->setData($data);
            if ($form->isValid()) {
                $data = $form->getData();

                $this->writeEntityManager->beginTransaction();
                try {
                    $rechargeCodeInfo   = $this->writeEntityManager->getRepository(RechargeCode::class)->findOneBy(['codeStr' => $data['rechargeCode']]);
                    $userInfo           = $this->writeEntityManager->getRepository(User::class)->findOneBy(['userId' => parent::$userId]);
                    if ($rechargeCodeInfo->getCodeMoney() > 0) {
                        $userMoney = $userInfo->getUserMoney() + $rechargeCodeInfo->getCodeMoney();
                        $this->balanceLogManager->addBalanceLog([
                            'userId'    => parent::$userId,
                            'userName'  => parent::$userName,
                            'balanceChangeType' => 6,
                            'balanceChangeNum'  => $rechargeCodeInfo->getCodeMoney(),
                            'balanceChangedAmount' => $userMoney,
                            'balanceChangeTime' => time(),
                            'balanceChangeInfo' => $this->translator->translate('充值码充值，充值码').' '.$data['rechargeCode']
                        ]);
                        $this->userManager->updateUserMoney($userMoney, $userInfo);
                        $this->rechargeCodeManager->editRechargeCode([
                            'userId'    => parent::$userId,
                            'userName'  => parent::$userName,
                            'codeRechargeTime' => time()
                        ], $rechargeCodeInfo);
                    }
                    $this->writeEntityManager->commit();

                    return $this->redirect()->toRoute('home-user-balance', ['action' => 'finishRechargeCode', 'id' => $rechargeCodeInfo->getCodeId()]);
                } catch (\Exception $e) {
                    $this->writeEntityManager->rollback();
                }
            }
        }

        return ['form' => $form];
    }

    /**
     * 充值码充值完成
     * @return array|\Laminas\Http\Response
     */
    public function finishRechargeCodeAction()
    {
        $this->layout()->setVariable('titleName', $this->translator->translate('充值码充值完成'));

        $codeId = $this->params()->fromRoute('id', 0);
        $chargeCodeInfo = $this->entityManager->getRepository(RechargeCode::class)->findOneBy(['codeId' => $codeId, 'userId' => parent::$userId]);
        if ($chargeCodeInfo == null) return $this->redirect()->toRoute('shop-home');

        return ['chargeCodeInfo' => $chargeCodeInfo];
    }

    /**
     * 账户充值
     * @return array|\Laminas\Http\Response
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function rechargeAction()
    {
        $view = new ViewModel();

        $this->layout()->setVariable('titleName', $this->translator->translate('现金充值'));

        //查看是否有未充值的信息
        $userRechargeInfo = $this->entityManager->getRepository(UserRecharge::class)->findOneBy(['userId' => parent::$userId, 'payState' => 10]);
        if($userRechargeInfo) return ['userRechargeInfo' => $userRechargeInfo, 'shopCurrency' => Common::configValue($userRechargeInfo->getCurrencyCode(), 'currency'), 'baseCurrency' => Common::configValue($userRechargeInfo->getBaseCurrencyCode(), 'currency')];

        $shopCurrency = $this->shopPlugin()->getShopDefaultCurrency();
        $baseCurrency = Common::configValue('default', 'currency');
        $paymentList = ShopCommon::shopPaymentList('true', $shopCurrency['code'], ['BalancePay']);

        $form = new UserRechargeForm($paymentList);
        if($this->getRequest()->isPost()) {
            $data = $this->params()->fromPost();
            $form->setData($data);
            if ($form->isValid()) {
                $data = $form->getData();
                $paymentConfig = ShopCommon::shopPaymentConfig($data['payCode']);
                $userRechargeInfo = $this->userRechargeManager->addUserRecharge(array_merge($data, [
                    'userId'            => parent::$userId,
                    'userName'          => parent::$userName,
                    'currencyCode'      => $shopCurrency['code'],
                    'currencyRate'      => $shopCurrency['rate'],
                    'baseRechargeNum'   => $data['rechargeNum']/$shopCurrency['rate'],
                    'baseCurrencyCode'  => $baseCurrency['code'],
                    'payCode'           => $data['payCode'],
                    'payName'           => $paymentConfig['paymentName']['content']
                ]));

                return $this->redirect()->toRoute('home-user-balance', ['action' => 'continueUserRecharge', 'id' => $userRechargeInfo->getRechargeId()]);
            }
        }

        return ['form' => $form, 'shopCurrency' => $shopCurrency, 'baseCurrency' => $baseCurrency, 'paymentList' => $paymentList];
    }

    /**
     * 充值继续支付
     * @return \Laminas\Http\Response|ViewModel
     */
    public function continueUserRechargeAction()
    {
        $view = new ViewModel();

        $rechargeId = (int) $this->params()->fromRoute('id', -1);
        $userRechargeInfo = $this->entityManager->getRepository(UserRecharge::class)->findOneBy(['userId' => parent::$userId, 'rechargeId' => $rechargeId, 'payState' => 10]);
        if($userRechargeInfo == null) return $this->redirect()->toRoute('shop-home');

        $returnUrl  = $this->url()->fromRoute('shop-return', ['action' => 'rechargePaymentReturn', 'id' => $userRechargeInfo->getRechargeId()], ['force_canonical' => true]);
        $notifyUrl  = $this->url()->fromRoute('shop-notify', ['action' => 'rechargePaymentNotify', 'id' => $userRechargeInfo->getRechargeId()], ['force_canonical' => true]);
        $cancelUrl  = $this->url()->fromRoute('home-user-balance', [], ['force_canonical' => true]);
        //微信公众号支付时，返回获取code，进而获取openid，非支付返回
        $wxReturnUrl= $this->url()->fromRoute('home-user-balance', ['action' => 'continueUserRecharge', 'id' => $userRechargeInfo->getRechargeId()], ['force_canonical' => true]);

        $payResult = ShopCommon::shopPaymentService($userRechargeInfo->getPayCode())->paymentTo(
            [
                'returnUrl' => $returnUrl,
                'notifyUrl' => $notifyUrl,
                'cancelUrl' => $cancelUrl,
                'wxReturnUrl'=> $wxReturnUrl,
                'sn'        => $userRechargeInfo->getPayCode().$userRechargeInfo->getAddRechargeTime(),
                'amount'    => $userRechargeInfo->getRechargeNum(),
                'currency'  => $userRechargeInfo->getCurrencyCode(),
                'subject'   => $userRechargeInfo->getUserName() . $this->translator->translate('余额充值')
            ]
        );
        //微信支付
        if (isset($payResult['type']) && in_array($userRechargeInfo->getPayCode(), ['Wxpay'])) {
            if (isset($_GET['code']) && $payResult['type'] == 'wechat') {//公众号支付
                $view->setTemplate('shop/home-user-balance/wechat-pay');
                return $view->setVariables(['userRechargeInfo' => $userRechargeInfo, 'result' => $payResult['result']]);
            }
            if ($payResult['type'] == 'scan') {//扫码支付
                $view->setTemplate('shop/home-user-balance/scan-pay');
                return $view->setVariables(['userRechargeInfo' => $userRechargeInfo, 'result' => $payResult['result']]);
            }
        }
        //其他支付
        return $payResult;
    }

    /**
     * 充值支付状态
     * @return JsonModel
     */
    public function ajaxRechargePaymentStatusAction()
    {
        $rechargeId = (int) $this->params()->fromRoute('id', -1);
        $userRechargeInfo = $this->writeEntityManager->getRepository(UserRecharge::class)->findOneBy(['userId' => parent::$userId, 'rechargeId' => $rechargeId]);
        if ($userRechargeInfo && $userRechargeInfo->getPayState() >= 20) return new JsonModel(['state' => 'true']);

        return new JsonModel(['state' => 'false']);
    }

    /**
     * 删除未支付的充值信息
     * @return \Laminas\Http\Response
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function deleteUserRechargeAction()
    {
        $rechargeId = (int) $this->params()->fromRoute('id', -1);
        $userRechargeInfo = $this->writeEntityManager->getRepository(UserRecharge::class)->findOneBy(['userId' => parent::$userId, 'rechargeId' => $rechargeId, 'payState' => 10]);
        if($userRechargeInfo == null) return $this->redirect()->toRoute('shop-home');

        $this->userRechargeManager->deleteUserRecharge($userRechargeInfo);

        return $this->redirect()->toRoute('home-user-balance', ['action' => 'recharge']);
    }

    /**
     * 余额提现页面
     * @return array
     */
    public function userWithdrawAction()
    {
        $this->layout()->setVariable('titleName', $this->translator->translate('账户余额提现'));

        $userInfo = $this->entityManager->getRepository(User::class)->findOneBy(['userId' => parent::$userId]);

        $page       = (int) $this->params()->fromQuery('page', 1);
        $query      = $this->entityManager->getRepository(UserWithdraw::class)->findUserWithdrawList(parent::$userId);
        $paginator  = $this->shopPlugin()->shopPaginator($query, $page);

        return ['userInfo' => $userInfo, 'userWithdrawList' => $paginator];
    }

    /**
     * 余额提现申请
     * @return array|\Laminas\Http\Response
     * @throws \Doctrine\ORM\ORMException
     * @throws \Doctrine\ORM\OptimisticLockException
     */
    public function addUserWithdrawAction()
    {
        $this->layout()->setVariable('titleName', $this->translator->translate('余额提现操作'));

        $userInfo = $this->entityManager->getRepository(User::class)->findOneBy(['userId' => parent::$userId]);

        $withdrawInfo = $this->entityManager->getRepository(UserWithdraw::class)->findOneBy(['userId' => parent::$userId, 'withdrawState' => 1]);
        if($withdrawInfo != null) {
            $this->flashMessenger()->addWarningMessage($this->translator->translate('您有待处理的提现申请，无法提交余额提现!'));
            return $this->redirect()->toRoute('home-user-balance', ['action' => 'userWithdraw']);
        }

        $form = new AddUserWithdrawForm($userInfo);
        if($this->getRequest()->isPost()) {
            $data = $this->params()->fromPost();
            $form->setData($data);
            if ($form->isValid()) {
                $data = $form->getData();
                $data['userId']    = parent::$userId;
                $data['userName']  = parent::$userName;
                $data['currencyCode'] = Common::configValue('default', 'currency')['code'];
                $this->userWithdrawManager->addUserWithdraw($data);

                $this->flashMessenger()->addSuccessMessage($this->translator->translate('余额提现申请完成!'));
                return $this->redirect()->toRoute('home-user-balance', ['action' => 'userWithdraw']);
            }
        }

        return ['form' => $form, 'userInfo' => $userInfo];
    }
}